package de.hochschuletrier.bachelor.antfarm.entity.ant;

import java.awt.Point;
import java.util.ArrayList;
import java.util.HashMap;

import de.hochschuletrier.bachelor.antfarm.entity.Ant;
import de.hochschuletrier.bachelor.antfarm.entity.Foodpiece;
import de.hochschuletrier.bachelor.antfarm.entity.Nest;
import de.hochschuletrier.bachelor.antfarm.entity.mes.ActionMessage;
import de.hochschuletrier.bachelor.antfarm.entity.mes.ActionMessageGroup;
import de.hochschuletrier.bachelor.antfarm.util.DistanceHelper;

public class Returnstate extends Antstate {
	
	public Returnstate(Ant ant) {
		int last = ant.getLastPositions().size() - 1;
		if (last > 0) {
			ant.getLastPositions().remove(last);
		}
	}

	@Override
	public void perform(Ant ant) {
		ActionMessageGroup g = new ActionMessageGroup();

		// Ist die Ameise schon an der Quelle?
		getToNest(ant, g);

		// Letzte Position finden-
		int last = ant.getLastPositions().size() - 1;
		
		if (last >= 0) {
			Point lastPosition = ant.getLastPositions().get(last);
			ant.getLastPositions().remove(last);

			// Bewegung durchführen
			doMove(lastPosition, ant, g);
			
			last = ant.getLastPositions().size() - 1;
			if (last > 0) {
				ant.getLastPositions().remove(last);
			}
		}
		else {
			performAlternative(ant);
		}
	}

	public void performAlternative(Ant ant) {
		ActionMessageGroup g = new ActionMessageGroup();

		// Mögliche Richtungen ausloten
		ArrayList<Point> possibleDirections = getDirections(ant, g);

		// Aus dem Level herauslaufen verhindern
		possibleDirections = preventGettingOutOfLevel(possibleDirections, ant, g);

		// Prüfen, ob Ziel in der Nähe ist
		if (DistanceHelper.getDistance(ant, ant.getNest()) <= 3f) {
			Nest nest = ant.getNest();

			// Ist die Ameise schon an der Quelle?
			getToNest(ant, g);

			// Näher an das Nest kommen
			float dist = -1;
			for (Point p : possibleDirections) {
				float currentDistance = DistanceHelper.getDistance(nest.getX(), nest.getY(), ant.getX() + p.x, ant.getY() + p.y);
				if (dist == -1 || currentDistance < dist) {
					dist = currentDistance;
				}
			}

			for (int i = possibleDirections.size() - 1; i >= 0; --i) {
				Point p = possibleDirections.get(i);
				float currentDistance = DistanceHelper.getDistance(nest.getX(), nest.getY(), ant.getX() + p.x, ant.getY() + p.y);
				if (currentDistance > dist) {
					g.addMessage(new ActionMessage("Habe Punkt (" + (ant.getX() + possibleDirections.get(i).x) + "|"
							+ (ant.getY() + possibleDirections.get(i).y) + ") entfernt weil ich damit nicht näher an Futterquelle komme", possibleDirections
							.get(i)));
					possibleDirections.remove(i);
				}
			}
		}

		// Pheromone beachten
		HashMap<Point, Integer> weightMap = evaluateMostPheromons(possibleDirections, ant, g);

		// Letzte Richtung entfernen
		//possibleDirections = removeLastDirections(possibleDirections, ant, g);
		weightMap = evaluateLastDirections(possibleDirections,ant,weightMap,g);

		// Bisherige Richtung zum Nest beibehalten
		weightMap = holdDirectionToNest(possibleDirections, ant, weightMap, g, false);

		// Bewegung möglichst gerade und nicht quer halten
		weightMap = doEasyMove(possibleDirections, ant, weightMap, g);
		
		// Zufall mindern
		weightMap = lessLuckCheck(possibleDirections, ant, weightMap, g);

		// Richtungen ausgeben
		echoDirections(possibleDirections, ant, weightMap, g);

		// Bewegung durchführen
		doMove(possibleDirections, ant, weightMap, g);
	}

	// Ist die Ameise schon an der Quelle?
	private void getToNest(final Ant ant, final ActionMessageGroup g) {
		Nest nest = ant.getNest();

		if (DistanceHelper.getDistance(ant.getX(), ant.getY(), nest.getX(), nest.getY()) <= 1f) {
			Foodpiece p = ant.getFoodpiece();
			ant.addMessage(g);
			g.addMessage(new ActionMessage("Habe Futter abgegeben!"));
			if (p != null) {
				nest.putFood(p, ant);
				switch (nest.getTaskForAnt()) {
				case collecting:
					ant.setState(new Collectstate());
					break;
				case scouting:
					ant.setState(new Searchstate(ant));
					break;
				default:
					System.err.println("Unknown Anttask");
					break;
				}
			}
			return;
		}
	}

	@Override
	public String getName() {
		return "Returning";
	}

}
